/**
 * 系列号
 */
let ELEMENT_SEQUENCE = {
    value:1000,
    next:function(){
        this.value+=1;
        return this.value;
    }
};

/**
 * 查询满足css选择器的dom元素
 * @param {string} selector css选择器
 * @returns HTMLElement
 */
function _selector(selector){
    return document.querySelector(selector);
}
/**
 * 查询满足css选择器的所有dom元素
 * @param {string} selector css选择器
 * @returns NodeList
 */
function _selectorAll(selector){
    return document.querySelectorAll(selector);
}

/**
 * 将下划线命名改为驼峰命名
 * @returns 
 */
String.prototype._toCameCase = function () {
    let array = this.split("_");
    let output = "";
    for (let i = 0; i < array.length; i++) {
        let item = array[i];
        if (i == 0) {
            output += item;
        } else {
            if (item.length > 0) {
                let newCase = item.substr(0, 1).toUpperCase();
                if (item.length > 1) {
                    newCase = newCase + item.substr(1, item.length - 1);
                }
                output += newCase;
            }
        }
    }
    return output;
};

/**
 * dom节点的class处理
 */
function ClassNameExtend() {
    /**
     * 判断当前元素是否有某个class
     * @param {string} className 搜索的类名
     * @returns boolean
     */
    this._hasClass = function (className) {
        return this.classList.contains(className);
    };
    /**
     * 为当前元素添加一个class
     * @param {string} className 
     * @returns HTMLElement
     */
    this._addClass = function (...className) {
        this.classList.add(...className);
        return this;
    };
    /**
     * 移除当前dom元素的某个class
     * @param {string} className 
     * @returns HTMLElement
     */
    this._removeClass = function (...className) {
        this.classList.remove(...className);
        return this;
    };
    /**
     * 如果存在oldClass则将其替换为newClass，否则新增newClass
     * @param {string} oldClass 被替换的类名
     * @param {string} newClass 新的类名
     * @returns HTMLElement
     */
    this._replaceClass = function (oldClass, newClass) {
        return this._removeClass(oldClass)._addClass(newClass);
    };
    /**
     * 如果存在className就删除，否则就添加
     * @param {string} className 
     * @returns HTMLElement
     */
    this._toggleClass = function (className) {
        this.classList.toggle(className);
        return this;
    };
    /**
     * 为当前元素添加指定的class，并且移除兄弟节点的该class
     * @param {string} className 
     */
    this._aloneClass=function(className){
        let parent = this.parentElement||this.parentNode;
        let children = parent.children;
        for(let i=0;i<children.length;i++){
            if(children[i]===this){
                children[i]._addClass(className);
            }else{
                children[i]._removeClass(className);
            }
        }
    };
}
/**
 * dom节点的css
 */
function CssExtend() {
    /**
     * 设置或获取dom元素的样式
     * @param {string} key style属性名称
     * @param {string|undefined} value style属性值，可空
     * @returns 
     */
    this._css = function (key, value) {
        let newKey = key._toCameCase();
        if (value != undefined) {
            //如果有value，该函数的功能为设置样式
            this.style[newKey] = value;
            return this;
        } else {
            //如果没有value，该函数的功能为获取样式
            if (this.style[newKey]) {
                //如果是行内样式，则直接返回
                return this.style[newKey];
            } else if (this.currentStyle) {
                //IE和Opera
                return this.currentStyle[newKey];
            } else {
                //w3c
                return window.getComputedStyle(this, null)[newKey];
            }
        }
    };
    /**
     * 获取或设置当前元素的数值类的样式，默认的单位为px
     * @param {string} key 
     * @param {string|number} value 
     * @returns HTMLElement|number
     */
    this._numbercss = function (key, value) {
        if (value === undefined) {
            value = this._css(key);
            return value ? parseInt(value) : 0;
        } else {
            value = typeof (value) === "string" ? value : `${value}px`;
            return this._css(key, value);
        }
    };
    /**
     * 显示当前元素
     * @returns 
     */
    this._show = function () {
        if (this._css("display") === "none") {
            this.style.display = this.getAttribute("_lastdisplay") || "block";
        }
        return this;
    };
    /**
     * 隐藏当前元素
     * @returns 
     */
    this._hide = function () {
        let display = this._css("display");
        if (display != "none") {
            this.setAttribute("_lastdisplay", display);
        }
        this.style.display = "none";
        return this;
    };
    this._width = function (width) {
        return this._numbercss("width", width);
    };
    this._height = function (height) {
        return this._numbercss("height", height);
    };
    this._boxsizing = function (boxSizing) {
        return this._css("boxSizing", boxSizing);
    };
    this._borderbox = function () {
        return this._css("boxSizing", "border-box");
    };
    this._contentbox = function () {
        return this._css("boxSizing", "content-box");
    };
    this._margin = function (margin) {
        return this._numbercss("margin", margin);
    };
    this._padding = function (padding) {
        return this._numbercss("padding", padding);
    };
    this._radius = function (borderRadius) {
        return this._numbercss("borderRadius", borderRadius);
    };
    this._border = function (borderStyle) {
        return this._css("border", borderStyle);
    };
    this._color = function (color) {
        return this._css("color", color);
    };
    this._bgcolor = function (backgroundColor) {
        return this._css("backgroundColor", backgroundColor);
    };
    this._size = function (fontSize) {
        return this._numbercss("fontSize", fontSize);
    };
    this._weight = function (fontWeight) {
        return this._css("fontWeight", fontWeight);
    };
    this._position = function (position) {
        return this._css("position", position);
    };
    this._absolute = function () {
        return this._css("position", "absolute");
    };
    this._relative = function () {
        return this._css("position", "relative");
    };
    this._display = function (display) {
        return this._css("display", display);
    };
    this._block = function () {
        return this._css("display", "block");
    };
    this._inline = function () {
        return this._css("display", "inline");
    };
    this._inlineblock = function () {
        return this._css("display", "inline-block");
    };
    this._shadown=function(shadow){
        return this._css("boxShadow",shadow);
    };
    /**
     * 设置dom元素的线性渐变
     * @param {string} duration 方向 to top|to right|to left|to bottom|to top left ... 
     * @param  {...string} colors 渐变的起始颜色和终结颜色
     * @returns HTMLElement
     */
    this._linear=function(duration,...colors){
        let cssString = `linear-gradient(${duration}`;
        for(let i=0;i<colors.length;i++){
            cssString+=`, ${colors[i]}`;
        }
        cssString+=")";
        return this._css("background-image",cssString);
    };
    /**
     * 设置dom元素的经向渐变
     * @param {*} startColor 起始颜色
     * @param  {...string} colors 终结颜色
     * @returns HTMLElement
     */
    this._radial=function(startColor,...colors){
        let cssString = `radial-gradient(${startColor}`;
        for(let i=0;i<colors.length;i++){
            cssString+=`, ${colors[i]}`;
        }
        cssString+=")";
        return this._css("background-image",cssString);
    };
    /**
     * 为当前元素创建动画
     * @param {number} duration 动画完成时间(秒)
     * @param  {...any} fromTo 每一帧的样式
     * @returns 
     */
    this._animation=function(duration,...fromTo){
        duration=duration||10;  //默认10秒钟完成动画

        let animationName=`sequence_${ELEMENT_SEQUENCE.next()}`;   //为动画命名
        let styleText = `@keyframes ${animationName}{`;
        let interval = parseInt(100.0/fromTo.length);           //时间线上的间隔

        styleText+=`0% {${fromTo[0]}}`;
        for(let i=1;i<fromTo.length-1;i++){
            styleText+=`${interval*i}% {${fromTo[i]}}`;
        }
        styleText+=`100% {${fromTo[fromTo.length-1]}}`;
        styleText+=`}`;
        styleText=styleText.replace(/;+/g,";");
        document.querySelector("head").insertAdjacentHTML("beforeend",`<style type="text/css">${styleText}</style>`);   //将动画插入到head
        return this._css("animation",`${animationName} ${parseInt(duration)}s`);
    };
}
/**
 * dom节点的属性
 */
function AttributeExtend() {
    /**
     * 获取或设置当前dom元素的属性
     * @param {string} key 
     * @param {object} value 
     * @returns HTMLElement|object
     */
    this._attr = function (key, value) {
        if(key==="checked"){
            //input type=checkbox一定要用强制的true和false
            if(value===undefined){
                return this.checked?true:false;
            }else{
                value=value?true:false;
            }
        }else{
            if (value === undefined) {
                return this.getAttribute(key);
            } else {
                this.setAttribute(key, value);
                return this;
            }
        } 
    };
    /**
     * 移除当前元素的属性
     * @param {string} key 属性名称
     * @returns HTMLElement
     */
     this._removeAttr = function (key) {
        this.removeAttribute(key);
        return this;
    };
    this._title = function(title){
        return this._attr("title",title);
    };
    this._src = function(title){
        return this._attr("src",title);
    };
    this._href = function(title){
        return this._attr("href",title);
    };
    /**
     * 设置或获取元素的选中状态
     * @param {*} value 当value为boolean时，元素的选中状态有true或false决定，当value为数组时，将匹配当前节点的子孙节点中的checkbox的value
     */
    this._checked=function(value){
        //注意强制用true(false)取代checked(undefine)
        if(value===undefined){
            return this.checked?true:false;
        }else{
            if(typeof(value)==="boolean"){
                this.checked = value;
            }else if(typeof(value)==="string" || typeof(value)==="number"){
                this.checked = this.value==value;
            }else if(value instanceof(Array)){
                //当value为数组的时候，将搜索当前元素的子节点中的所有input[type=checkbox]
                this._selectorAll("input[type='checkbox']")._for(function(item){
                    let checked = false;
                    for(let i=0;i<checked.length;i++){
                        if(item.value==checked[i]){
                            checked=true;
                            break;
                        }
                    }
                    item.checked = checked;
                });
            }
        }
    };
    /**
     * 为当前元素设置属性，并且移除兄弟节点的该属性
     * @param {string} key 属性名称
     * @param {string|number|boolean} value 属性值
     */
    this._aloneAttr = function(key,value){
        let parent = this.parentElement||this.parentNode;
        let children = parent.children;
        for(let i=0;i<children.length;i++){
            if(children[i]===this){
                children[i]._attr(key,value);
            }else{
                children[i]._removeAttr(key);
            }
        }
    };
    /**
     * 设置或获取当前元素内部的html
     * @param {string|undefined} html HTML字符串
     * @returns HTMLElement|string
     */
    this._html = function (html) {
        if (html) {
            this.innerHTML = html;
            return this;
        } else {
            return this.innerHTML;
        }
    };
    /**
     * 设置或获取当前元素内部的文本
     * @param {string|undefined} text 文本
     * @returns HTMLElement|string
     */
    this._text = function (text) {
        if (text) {
            this.innerText = text;
            return this;
        } else {
            return this.innerText;
        }
    };
    /**
     * 设置或获取表单元素的value属性
     * @param {*|undefined} value 
     * @returns HTMLElement|string
     */
    this._value = function (value) {
        if (value === undefined) {
            value = "";
            if (this instanceof HTMLInputElement || this instanceof HTMLTextAreaElement) {
                value = this.value;
            } else if (this instanceof HTMLSelectElement) {
                let index = this.selectedIndex;
                value = this.options[index].value;
            } 
            return value;
        } else {
            if (this instanceof HTMLInputElement || this instanceof HTMLTextAreaElement) {
                this.value = value;
            } else if (this instanceof HTMLSelectElement) {
                let selectedOption = this._selector(`[value='${value}']`);
                if(selectedOption){
                    selectedOption._aloneAttr("selected","selected");
                }
            } 
            return this;
        }
    };
}
/**
 * dom节点的上下文
 */
function ContextExtend() {
    /**
     * 在当前节点查找符合css选择器的节点
     * @param {string} selector css选择器
     * @returns HTMLElement
     */
    this._selector=function(selector){
        return this.querySelector(selector);
    };
    /**
     * 在当前节点查找符合css选择器的节点
     * @param {string} selector css选择器
     * @returns NodeList
     */
    this._selectorAll=function(selector){
        return this.querySelectorAll(selector);
    };
    /**
     * 查找当前dom元素在其直接父节点的子节点中的下标
     * @returns number
     */
    this._index = function () {
        let parent = this.parentElement || this.parentNode;
        let children = parent.children;
        let index = 0;
        for (let i = 0; i < children.length; i++) {
            if (children[i] === this) {
                index = i;
                break;
            }
        }
        return index;
    };
    /**
     * 将当前元素追加到目标节点
     * @param {HTMLElement} target 目标节点
     * @returns HTMLElement
     */
    this._appendTo = function (target) {
        target = typeof(target)==="string"?document.querySelector(target):target;
        target.appendChild(this);
        return this;
    };
    /**
     * 将当前dom元素插入到目标节点内部的前面
     * @param {HTMLElement} target 目标节点
     * @returns HTMLElement
     */
    this._prependTo = function (target) {
        let children = target.children;
        if (!children.length) {
            target.appendChild(this);
        } else {
            target.insertBefore(this, children[0]);
        }
        return this;
    };
    /**
     * 在当前元素指定位置插入html或元素
     * @param {string} where 插入的位置beforebegin|afterbegin|beforeend|afterend
     * @param {string|HTMLElement} content 待插入的html字符串或元素
     * @returns 
     */
    this._adjacent=function(where,content){
        if (content instanceof HTMLElement) {
            this.insertAdjacentElement(where, content);
        } else {
            this.insertAdjacentHTML(where, content);
        }
        return this;
    };
    /**
     * 在当前节点的开始标签之前插入节点或HTML
     * @param {HTMLElement|string} content 节点或HTML字符串
     * @returns 
     */
    this._beforeBegin = function (content) {
        return this._adjacent("beforebegin",content);
    };
    /**
     * 在当前节点的开始标签之后插入节点或HTML
     * @param {HTMLElement|string} content 节点或HTML字符串
     * @returns 
     */
    this._afterBegin = function (content) {
        return this._adjacent("afterbegin",content);
    };
    /**
     * 在当前节点的结束标签之前插入节点或HTML
     * @param {HTMLElement|string} content 节点或HTML字符串
     * @returns 
     */
    this._beforeEnd = function (content) {
        return this._adjacent("beforeend",content);
    };
    /**
     * 在当前节点的结束标签之后插入节点或HTML
     * @param {HTMLElement|string} content 节点或HTML字符串
     * @returns 
     */
    this._afterEnd = function (content) {
        return this._adjacent("afterend",content);
    };
    /**
     * 将当dom元素从文档流中移除，移除后的元素仍然可用，只是不在文档流中
     * @returns HTMLElement
     */
    this._remove = function () {
        let parent = this.parentElement || this.parentNode;
        parent.removeChild(this);
        return this;
    };
    /**
     * 在当前dom元素的外围包裹HTML代码
     * @param {*} beforeHTML 开始标签之前的HTML
     * @param {*} afterHTML  结束标签之后的HTML
     * @returns 
     */
    this._wrap = function (beforeHTML, afterHTML) {
        if (afterHTML) {
            beforeHTML += afterHTML;
        }
        this._beforeBegin(beforeHTML);
        this._appendTo(this.previousElementSibling);
        return this;
    };
    /**
     * 去除当前节点的父节点
     * @returns 
     */
    this._unwrap = function () {
        let parent = this.parentElement || this.parentNode;
        let html = parent._html();
        parent._beforeBegin(html);
        parent._remove();
        return this;
    };
}
/**
 * 节点的事件处理
 */
function EventExptend() {
    /**
     * 监听当前节点的事件
     * @param {string} eventType 事件类型
     * @param {function} eventHandler function(element,event,target)
     * @returns HTMLElement
     */
    this._on = function (eventType, eventHandler) {
        this.addEventListener(eventType, function (event) {
            event = event || window.event;
            let target = event.srcElement || event.target;
            eventHandler(this, event, target);
        });
        return this;
    };
    /**
     * 监听子节点的事件
     * @param {string} eventType 事件类型
     * @param {string} selector 子孙节点选择器
     * @param {function} eventHandler function(element,event,target)
     * @returns HTMLElement
     */
    this._listen = function (eventType, selector, eventHandler) {
        if (selector === null) {
            //_listen(eventType,null,callback)的调用方式
            this._on(eventType, eventHandler);
        } else if (arguments.length === 2) {
            //_listen(eventType,callback)的调用方式
            this._on(eventType, arguments[1]);
        } else {
            //_listen(eventType,selector,callback)的调用方式
            this.addEventListener(eventType, function (event) {
                let nodeList = this.querySelectorAll(selector);
                event = event || window.event;
                let target = event.srcElement || event.target;
                let inList = false;
                for (let i = 0; i < nodeList.length; i++) {
                    if (nodeList[i] === target) {
                        inList = true;
                        break;
                    }
                }
                if (inList) {
                    eventHandler(this, event, target);
                }
            });
        }
        return this;
    };
    //以下为已命名的事件
    this._click=function(eventHandler){
        return this._on("click",eventHandler);
    };
    this._dblclick=function(eventHandler){
        return this._on("dblclick",eventHandler);
    };
    this._mousedown=function(eventHandler){
        return this._on("mousedown",eventHandler);
    };
    this._mouseup=function(eventHandler){
        return this._on("mouseup",eventHandler);
    };
    this._mousemove=function(eventHandler){
        return this._on("mousemove",eventHandler);
    };
    this._mouseover=function(eventHandler){
        return this._on("mouseover",eventHandler);
    };
    this._keydown=function(eventHandler){
        return this._on("keydown",eventHandler);
    };
    this._keyup=function(eventHandler){
        return this._on("keyup",eventHandler);
    };
    this._keypress=function(eventHandler){
        return this._on("keypress",eventHandler);
    };
    this._focus=function(eventHandler){
        return this._on("focus",eventHandler);
    };
    this._blur=function(eventHandler){
        return this._on("blur",eventHandler);
    };
    this._input=function(eventHandler){
        return this._on("input",eventHandler);
    };
    this._change=function(eventHandler){
        return this._on("change",eventHandler);
    };
}
/**
 * dom节点之间的四则运算
 */
function MathExtend() {
    /**
     * 重载元素的valueOf函数，使其能够进行四则运算
     * @returns 
     */
    this.valueOf = function () {
        let value = this._value();
        value = isNaN(value)?"0":value;
        let number = value.indexOf(".") >= 0 ? parseFloat(value) : parseInt(value);
        return number;
    };
    /**
     * 当前元素的值=给定集合中每一个元素的值之和
     * @param {HTMLCollection|Array<HTMLElement>|NodeList|string} selector 
     * @param {string|undefine} eventType 用什么事件来监听seletor的变化
     * @returns 
     */
    this._sumof = function (selector, eventType) {
        let sum = 0;
        let nodes = typeof (selector) === "string" ? document.querySelectorAll(selector) : selector;
        for (let i = 0; i < nodes.length; i++) {
            sum += nodes[i];
        }
        let _this = this;
        if (eventType) {
            for (let i = 0; i < nodes.length; i++) {
                nodes[i]._on(eventType, function () {
                    _this._sumof(nodes, null);
                });
            }
        }
        return this._value(sum);
    };
    /**
     * 当前元素的值=给定集合中每一个元素的值之最大值
     * @param {HTMLCollection|Array<HTMLElement>|NodeList|string} selector 
     * @param {string|undefine} eventType 用什么事件来监听seletor的变化
     * @returns 
     */
    this._maxof = function (selector, eventType) {
        let nodes = typeof (selector) === "string" ? document.querySelectorAll(selector) : selector;
        let max = Math.max(...nodes);
        let _this = this;
        if (eventType) {
            for (let i = 0; i < nodes.length; i++) {
                nodes[i]._on(eventType, function () {
                    _this._maxof(nodes, null);
                });
            }
        }
        return this._value(max);
    };
    /**
     * 当前元素的值=给定集合中每一个元素的值之最下值
     * @param {HTMLCollection|Array<HTMLElement>|NodeList|string} selector 
     * @param {string|undefine} eventType 用什么事件来监听seletor的变化
     * @returns 
     */
    this._minof = function (selector, eventType) {
        let nodes = typeof (selector) === "string" ? document.querySelectorAll(selector) : selector;
        let min = Math.min(...nodes);
        let _this = this;
        if (eventType) {
            for (let i = 0; i < nodes.length; i++) {
                nodes[i]._on(eventType, function () {
                    _this._minof(nodes, null);
                });
            }
        }
        return this._value(min);
    };
    /**
     * 当前元素的值=给定集合中每一个元素的值相串接
     * @param {HTMLCollection|Array<HTMLElement>|NodeList|string} selector 
     * @param {string} eventType 目标元素在发送eventType指定的事件时，当前元素的值将重新计算
     * @returns 
     */
    this._joinof = function (selector, eventType) {
        let nodes = typeof (selector) === "string" ? document.querySelectorAll(selector) : selector;
        let str = "";
        for (let i = 0; i < nodes.length; i++) {
            str += nodes[i]._value();
        }
        let _this = this;
        if (eventType) {
            for (let i = 0; i < nodes.length; i++) {
                nodes[i]._on(eventType, function () {
                    _this._joinof(nodes, null);
                });
            }
        }
        return this._value(str);
    };
}
function ArrayExtend() {
    /**
     * 求当前数组与另一个数组的交集
     * @param {Array|HTMLCollection|NodeList} other 另一个数组
     * @returns Array
     */
    this._intersect = function (other) {
        let result = [];
        for(let i=0;i<this.length;i++){
            let ok = false;
            for(let j=0;j<other.length;j++){
                if(this[i]===other[j]){
                    ok=true;
                    break;
                }
            }
            if(ok){
                result.push(this[i]);
            }
        }
        return result;
    };
    /**
     * 循环
     * @param {function} handler function(item,index){}
     * @returns Array
     */
    this._for = function (handler) {
        for (let i = 0; i < this.length; i++) {
            handler(this[i], i);
        }
        return this;
    };
    /**
     * 从最后一个元素开始向前迭代
     * @param {*} handler function(item,index){}
     * @returns Array
     */
    this._refor= function (handler) {
        for (let i = this.length-1; i >=0; i--) {
            handler(this[i], i);
        }
        return this;
    };
    //className
    this._addClass = function (className) {
        return this._for(item => item._addClass(className));
    };
    this._removeClass = function (className) {
        return this._for(item => item._removeClass(className));
    };
    this._hasClass = function (className) {
        return this.length === 0 ? false : this[0]._hasClass(className);
    };
    this._replaceClass = function (oldClass, newClass) {
        return this._for(item => item._replaceClass(oldClass, newClass));
    };
    this._toggleClass = function (className) {
        return this._for(item => item._toggleClass(className));
    };
    this._aloneClass = function(className){
        return this._for(item=>item._aloneClass(className));
    };
    //css
    this._css = function (key, value) {
        return value===undefined?this[0]._css(key):this._for(item=>item._css(key,value));
    };
    this._show = function () {
        return this._for(item=>item._show());
    };
    this._hide = function () {
        return this._for(item=>item._hide());
    };
    this._width = function (width) {
        return this._for(item=>item._width(width));
    };
    this._height = function (height) {
        return this._for(item=>item._height(height));
    };
    this._boxsizing = function (boxSizing) {
        return this._for(item=>item._boxsizing(boxSizing));
    };
    this._borderbox = function () {
        return this._for(item=>item._borderbox());
    };
    this._contentbox = function () {
        return this._for(item=>item._contentbox());
    };
    this._margin = function (margin) {
        return this._for(item=>item._margin(margin));
    };
    this._padding = function (padding) {
        return this._for(item=>item._padding(padding));
    };
    this._radius = function (borderRadius) {
        return this._for(item=>item._radius(borderRadius));
    };
    this._border = function (borderStyle) {
        return this._for(item=>item._border(borderStyle));
    };
    this._color = function (color) {
        return this._for(item=>item._color(color));
    };
    this._bgcolor = function (backgroundColor) {
        return this._for(item=>item._bgcolor(backgroundColor));
    };
    this._size = function (fontSize) {
        return this._for(item=>item._size(fontSize));
    };
    this._weight = function (fontWeight) {
        return this._for(item=>item._weight(fontWeight));
    };
    this._position = function (position) {
        return this._for(item=>item._position(position));
    };
    this._absolute = function () {
        return this._for(item=>item._absolute());
    };
    this._relative = function () {
        return this._for(item=>item._relative());
    };
    this._display = function (display) {
        return this._for(item=>item._display(display));
    };
    this._block = function () {
        return this._for(item=>item._block());
    };
    this._inline = function () {
        return this._for(item=>item._inline());
    };
    this._inlineblock = function () {
        return this._for(item=>item._inlineblock());
    };
    //attribute
    this._attr = function (key, value) {
        return value===undefined?this[0]._attr(key):this._for(item=>item._attr(key,value));
    };
    this._removeAttr = function (attributeName) {
        return this._for(item=>item._removeAttr(attributeName));
    };
    this._html = function (content) {
        return content===undefined?this[0]._html():this._for(item=>item._html(content));
    };
    this._text = function (content) {
        return content===undefined?this[0]._text():this._for(item=>item._text(content));
    };
    this._value = function (value) {
        return content===undefined?this[0]._value():this._for(item=>item._value(value));
    };
    //event
    this._on = function (eventType, eventHandler) {
        return this._for(item=>item._on(eventType,eventHandler));
    };
    this._click=function(eventHandler){
        return this._for(item=>item._click(eventHandler));
    };
    this._dblclick=function(eventHandler){
        return this._for(item=>item._dblclick(eventHandler));
    };
    this._mousedown=function(eventHandler){
        return this._for(item=>item._mousedown(eventHandler));
    };
    this._mouseup=function(eventHandler){
        return this._for(item=>item._mouseup(eventHandler));
    };
    this._mousemove=function(eventHandler){
        return this._for(item=>item._mousemove(eventHandler));
    };
    this._mouseover=function(eventHandler){
        return this._for(item=>item._mouseover(eventHandler));
    };
    this._keydown=function(eventHandler){
        return this._for(item=>item._keydown(eventHandler));
    };
    this._keyup=function(eventHandler){
        return this._for(item=>item._keyup(eventHandler));
    };
    this._keypress=function(eventHandler){
        return this._for(item=>item._keypress(eventHandler));
    };
    this._focus=function(eventHandler){
        return this._for(item=>item._focus(eventHandler));
    };
    this._blur=function(eventHandler){
        return this._for(item=>item._blur(eventHandler));
    };
    this._input=function(eventHandler){
        return this._for(item=>item._input(eventHandler));
    };
    this._change=function(eventHandler){
        return this._for(item=>item._change(eventHandler));
    };
    //context
    this._appendTo = function (target) {
        return this._for(item=>item._appendTo(target));
    };
    this._prependTo = function (target) {
        return this._refor(item=>item._prependTo(target));
    };
    this._adjacent=function(where,content){
        return this._for(item=>item._adjacent(where,content));
    };
    this._beforeBegin = function (content) {
        return this._for(item=>item._beforeBegin(content));
    };
    this._afterBegin = function (content) {
        return this._for(item=>item._afterBegin(content));
    };
    this._beforeEnd = function (content) {
        return this._for(item=>item._beforeEnd(content));
    };
    this._afterEnd = function (content) {
        return this._for(item=>item._afterEnd(content));
    };
    this._remove = function () {
        return this._for(item=>item._remove());
    };
    this._wrap = function (beforeHTML, afterHTML) {
        return this._for(item=>item._wrap(beforeHTML,afterHTML));
    };
    this._unwrap = function () {
        return this._for(item=>item._unwrap());
    };
}

ClassNameExtend.call(HTMLElement.prototype);
CssExtend.call(HTMLElement.prototype);
AttributeExtend.call(HTMLElement.prototype);
ContextExtend.call(HTMLElement.prototype);
EventExptend.call(HTMLElement.prototype);
MathExtend.call(HTMLElement.prototype);

ArrayExtend.call(Array.prototype);
ArrayExtend.call(HTMLCollection.prototype);
ArrayExtend.call(NodeList.prototype);

/**
 * 视图模型
 * @param {*} options 
 */
HTMLElement.prototype._mvvm=function(options){
    //将配置项解构到局部变量
    const model = options.model;              
    const controller = options.controller;  
    let view = this;

    //处理文本节点{{propertyName}}，在其容器上增加属性_bind="innerText:propertyName"
    view._selectorAll("*")._for(function(item){
        if(!item.children.length){
            //没有子节点的即为文本节点
            let text = item._text();
            let reg = /^\s*\{\{(\w+)\}\}\s*$/;
            if(reg.test(text)){
                item._attr("_bind",`innerText:${text.match(reg)[1]}`);
            }
        }
    });

    //构建viewModel
    const viewModel = {};     //viewModel={property1:[{arribute:"value",dataType:"boolean",element:...}, ...],property2:[...]}
    for(let key in model){
        const array = [];
        view._selectorAll(`[_bind$='\:${key}']`)._for(function(element){
            const attr_pro = element._attr("_bind").split(":");
            let attribute = attr_pro[0];
            let dataType = typeof(model[key]);
            if(dataType==="object"){
                if(model[key] instanceof Array){
                    dataType="array";
                }
            }
            const item={
                attribute:attribute,
                dataType:dataType,
                element:element
            }
            element._removeAttr("_bind");
            array.push(item);
        });
        viewModel[key]=array;
    }

    //创建model的代理
    const modelProxy = new Proxy(model,{
        get:function(client,propertyName){
            return client[propertyName];
        },
        set:function(client,propertyName,value){
            viewModel[propertyName]._for(function(item){
                if(item.attribute==="checkbox"){
                    //视当前节点为容器，搜索其下的checkbox，其值存在于数组中的checkbox被选中
                    item.element._selectorAll("input[type='checkbox']")._for(function(checkbox){
                        let checked = false;
                        for(let i=0;i<value.length;i++){
                            if(value[i]==checkbox.value){
                                checked=true;
                                break;
                            }
                        }
                        checkbox.checked = checked;
                    });
                }else if(item.attribute==="radio"){
                    //视当前节点我容器，搜索其下的radio,选中其值于value相等的radio
                    item.element._selectorAll("input[type='radio']")._for(function(radio){
                        radio.checked=radio.value==value.toString();
                    });
                }
                else if(item.attribute==="value"){
                    item.element._value(value);
                }else if(item.attribute==="checked"){
                    item.element.checked=value;
                }
                else{
                    item.element[item.attribute]=value;
                }
            });
            client[propertyName]=value;
            console.log(JSON.stringify(modelProxy))
        }
    });

    //此处不是为了给代理赋值，而是通过代理的set方法初始化页面
    for(let key in model){
        modelProxy[key]=model[key];
    }

    //为元素绑定input事件
    for(let propertyName in model){
        viewModel[propertyName]._for(function(item){
            item.element._input(function(ele,event,target){
                if(item.attribute==="checkbox"){
                    const array = [];
                    item.element._selectorAll("input[type='checkbox']")._for(function(checkbox){
                        if(checkbox.checked){
                            array.push(checkbox.value);
                        }
                    });
                    modelProxy[propertyName]=array;
                }else if(item.attribute==="value"){
                    let value = ele._value();
                    if(item.dataType==="number"){
                        if(!value.isNaN){
                            if(value.indexOf(".")>=0){
                                modelProxy[propertyName]=parseFloat(value);
                            }else{
                                modelProxy[propertyName]=parseInt(value);
                            }
                        }
                    }else{
                        modelProxy[propertyName]=value;
                    }
                }else if(item.attribute==="radio"){
                    let radio = item.element._selector("input:checked");
                    let value = radio.value;
                    if(item.dataType==="boolean"){
                        modelProxy[propertyName]= value==="true";
                    }else if(item.dataType==="number"){
                        if(!value.isNaN){
                            if(value.indexOf(".")>=0){
                                modelProxy[propertyName]=parseFloat(value);
                            }else{
                                modelProxy[propertyName]=parseInt(value);
                            }
                        }
                    }else{
                        modelProxy[propertyName]=value;
                    }
                }
                else if(item.attribute==="checked"){
                    modelProxy[propertyName]=item.element.checked;
                }
            });   
        });
    }
    //监听事件
    view._selectorAll("[_on]")._for(function(item){
        let controllerName = item._attr("_on"); 
        let eventType = controllerName.split(":")[0];
        let methodName = controllerName.split(":")[1];
        item._removeAttr("_on");
        item._on(eventType,function(ele,event,target){
            controller[methodName].call(modelProxy,ele,event,target);
        });
    });
    return modelProxy;
}